﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml;
using System.Windows.Input;
using System;
using SHomeWorkshop.LunarConcept.Controls;
using SHomeWorkshop.LunarConcept.Adorners;
using SHomeWorkshop.LunarConcept.Tools;
using SHomeWorkshop.LunarConcept.Enums;
using SHomeWorkshop.LunarMind;

namespace SHomeWorkshop.LunarConcept.Widgets
{
    /// <summary>
    /// 创建时间：2012年1月23日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：括弧线部件。
    /// </summary>
    public class BracketWidget : ArrowLineWidget, Interfaces.ICanSameSize, Interfaces.ITextRotate
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态构造方法]
        /// </summary>
        static BracketWidget()
        {
            dashArray = new DoubleCollection() { 2, 2 };
        }

        /// <summary>
        /// [构造方法]
        /// </summary>
        public BracketWidget(PageEditorReader masterEditor)
            : base(masterEditor)
        {
            widgetType = Enums.WidgetTypes.Bracket;
            widgetClassLocalName = Widget.GetWidgetClassLocalName(this.GetType().Name);

            arrows = ArrowType.None;//默认不需要箭头。

            mainPath.Data = new PathGeometry();
            mainPathFigure = new PathFigure() { IsClosed = false };
            (mainPath.Data as PathGeometry).Figures.Add(mainPathFigure);
            mainPathFigure.Segments.Add(mainPolyBezierSegment);

            mainPath.Fill = null;
            mainPath.Stroke = WidgetForeColor;
            
            this.mainCanvas.Children.Add(mainPath);

            Canvas.SetZIndex(mainPath, 0);

            #region 两个箭头。
            //startArrowPath.Cursor = Cursors.Arrow;
            startArrowPath.Fill = startArrowPath.Stroke = WidgetForeColor;
            startArrowPath.StrokeThickness = widgetLineWidth;
            PathGeometry startArrowPg = new PathGeometry();
            startArrowPath.Data = startArrowPg;

            startArrowPathFigure.IsClosed = true;
            startArrowPathFigure.IsFilled = true;
            startArrowPathFigure.Segments.Add(startArrowPolyLineSegment);

            startArrowPg.Figures.Add(startArrowPathFigure);

            //endArrowPath.Cursor = Cursors.Arrow;
            endArrowPath.Fill = endArrowPath.Stroke = WidgetForeColor;
            endArrowPath.StrokeThickness = widgetLineWidth;
            PathGeometry endArrowPg = new PathGeometry();
            endArrowPath.Data = endArrowPg;

            endArrowPathFigure.IsClosed = true;
            endArrowPathFigure.IsFilled = true;
            endArrowPathFigure.Segments.Add(endArrowPolyLineSegment);

            endArrowPg.Figures.Add(endArrowPathFigure);

            mainCanvas.Children.Add(startArrowPath);
            mainCanvas.Children.Add(endArrowPath);

            Canvas.SetZIndex(startArrowPath, 1);
            Canvas.SetZIndex(endArrowPath, 1);
            #endregion
            
            this.commentAdorner = new CommentAdorner(this.mainPath, this) { Visibility = System.Windows.Visibility.Collapsed };//默认不显示。

            this.hyperLinkAdorner = new HyperLinkAdorner(this.mainPath, this) { Visibility = Visibility.Collapsed };
            this.hyperLinkAdorner.MouseLeftButtonUp += new MouseButtonEventHandler(hyperLinkAdorner_MouseLeftButtonUp);

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.mainCanvas);
            if (adornerLayer == null)
            {
                MessageBox.Show("　　未找到Widget的装饰层！", LunarMind.Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            else
            {
                adornerLayer.Add(this.commentAdorner);//这个要在各具体部件类中添加。
                adornerLayer.Add(this.hyperLinkAdorner);//这个要在各具体部件类中添加。
            }
            
            //最后添加文本面板。//已移动到基类中。2013年3月13日
            //this.mainCanvas.Children.Add(this.mainTextPanel);
            //Canvas.SetZIndex(this.mainTextPanel, 2);
        }

        #endregion


        #region 字段与属性===================================================================================================

        public override Point BottomRight
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(startPoint.X, endPoint.X);
                maxRight = Math.Max(startPoint.X, endPoint.X);

                minTop = Math.Min(startPoint.Y, endPoint.Y);
                maxBottom = Math.Max(startPoint.Y, endPoint.Y);

                return new Point(maxRight, maxBottom);
            }
        }
        
        /// <summary>
        /// [只读]取括弧开口方向。
        /// </summary>
        private BracketOpenDirection BracketDirection
        {
            get
            {
                BracketOpenDirection direction;

                if (Math.Abs(endPoint.X - startPoint.X) < Math.Abs(endPoint.Y - startPoint.Y))
                {
                    //水平间距短
                    if (endPoint.X < startPoint.X)
                    {
                        direction = BracketOpenDirection.Left;
                    }
                    else
                    {
                        direction = BracketOpenDirection.Right;
                    }
                }
                else
                {
                    //垂直间距短
                    if (endPoint.Y < startPoint.Y)
                    {
                        direction = BracketOpenDirection.Up;
                    }
                    else
                    {
                        direction = BracketOpenDirection.Down;
                    }
                }

                return direction;
            }
        }
        
        private Point endPoint = new Point();
        /// <summary>
        /// [读写]线的终点坐标。
        /// </summary>
        [Tools.LunarProperty("EndPoint", PropertyDateType.Point)]
        public Point EndPoint
        {
            get { return endPoint; }
            set
            {
                endPoint = FormatPoint(value);
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.EndPointTag, endPoint.ToString());
                }

                RefreshLocation();
            }
        }

        private bool isTextAtClose = true;
        /// <summary>
        /// [读写]文本区是否位于括弧收口侧。若为false则位于开口一侧。默认为true。
        /// </summary>
        [LunarProperty("IsTextAtClose", PropertyDateType.Bool)]
        public bool IsTextAtClose
        {
            get { return isTextAtClose; }
            set
            {
                isTextAtClose = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.IsTextAtLeftOrTopTag, value.ToString());
                }
                this.RefreshTextPanelLocatin();
            }
        }

        private BracketLineForms lineForm = BracketLineForms.Bracket;
        /// <summary>
        /// [读写]设置线的形态。
        /// </summary>
        [Tools.LunarProperty("LineForm", PropertyDateType.BracketLineForm)]
        public BracketLineForms LineForm
        {
            get { return lineForm; }
            set
            {
                lineForm = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.LineFormTag, value.ToString());
                }

                this.RefreshLocation();
            }
        }

        private PolyBezierSegment mainPolyBezierSegment = new PolyBezierSegment();

        private Path mainPath = new Path()
        {
            Cursor = Cursors.Hand,
            StrokeLineJoin = PenLineJoin.Round,
            StrokeEndLineCap = PenLineCap.Round,
            StrokeStartLineCap = PenLineCap.Round
        };

        public Path MainPath
        {
            get { return mainPath; }
        }

        private PathFigure mainPathFigure;

        public PathFigure MainPathFigure
        {
            get { return mainPathFigure; }
        }
        
        private Point startPoint = new Point(0, 0);
        /// <summary>
        /// [读写]线的起点坐标。
        /// </summary>
        [Tools.LunarProperty("StartPoint", PropertyDateType.Point)]
        public Point StartPoint
        {
            get { return startPoint; }
            set
            {
                startPoint = FormatPoint(value);
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.StartPointTag, startPoint.ToString());
                }

                RefreshLocation();
            }
        }

        private double textRotateAngle = 0;
        /// <summary>
        /// [读写]文本旋转角度。取值范围：[-180,180]。
        /// </summary>
        [Tools.LunarProperty("TextRotateAngle", PropertyDateType.Double)]
        public double TextRotateAngle
        {
            get { return textRotateAngle; }
            set
            {
                if (value > 180)
                {
                    textRotateAngle = 180;
                }
                else if (value < -180)
                {
                    textRotateAngle = -180;
                }
                else
                {
                    textRotateAngle = value;
                }

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.TextRotateAngleTag, textRotateAngle.ToString());
                }

                this.RefreshTextRotateAngle();
            }
        }

        public override Point TopLeft
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(startPoint.X, endPoint.X);
                maxRight = Math.Max(startPoint.X, endPoint.X);

                minTop = Math.Min(startPoint.Y, endPoint.Y);
                maxBottom = Math.Max(startPoint.Y, endPoint.Y);

                return new Point(minLeft, minTop);
            }
        }

        #endregion


        #region 方法=========================================================================================================

        public override void Build()
        {
            base.Build();

            if (this.xmlData == null) return;

            XmlAttribute attrStartPoint = this.xmlData.GetAttribute(XmlTags.StartPointTag);
            if (attrStartPoint != null)
            {
                this.startPoint = FormatPoint(Point.Parse(attrStartPoint.Value));
            }

            XmlAttribute attrEndPoint = this.xmlData.GetAttribute(XmlTags.EndPointTag);
            if (attrEndPoint != null)
            {
                this.endPoint = FormatPoint(Point.Parse(attrEndPoint.Value));
            }

            XmlAttribute attrIsTextAtClose = this.xmlData.GetAttribute(XmlTags.IsTextAtCloseTag);
            if (attrIsTextAtClose != null)
            {
                this.isTextAtClose = bool.Parse(attrIsTextAtClose.Value);
            }
            else
            {
                //保持兼容而保留，其实含义不准。其它部件类型会使用XmlTags.IsTextAtLeftOrTopTag，即使不考虑兼容，也不能删除这个标签。
                XmlAttribute attrIsTextAtLeftOrTop = this.xmlData.GetAttribute(XmlTags.IsTextAtLeftOrTopTag);
                if (attrIsTextAtLeftOrTop != null)
                {
                    this.isTextAtClose = bool.Parse(attrIsTextAtLeftOrTop.Value);
                }
            }

            XmlAttribute attrTextRotateAngle = this.xmlData.GetAttribute(XmlTags.TextRotateAngleTag);
            if (attrTextRotateAngle != null)
            {
                this.textRotateAngle = double.Parse(attrTextRotateAngle.Value);
            }

            XmlAttribute attrBracketForm = this.xmlData.GetAttribute(XmlTags.LineFormTag);
            if (attrBracketForm != null)
            {
                this.lineForm = (Enums.BracketLineForms)Enum.Parse(typeof(Enums.BracketLineForms), attrBracketForm.Value);
            }

            this.RefreshTextRotateAngle();
            //包含RefreshArrows()调用。
            this.RefreshLocation();

            //此类是下面这几个属性的“最终实现类”。这些属性的值都已在基类确定。因此调用,
            this.RefreshWidgetLineColor();
            this.RefreshWidgetLineWidth();
            this.RefreshLineDash();

        }
        
        /// <summary>
        /// 根据“IsLinked”的结果分别重绘线条。
        /// </summary>
        public void DrawLine()
        {
            if (masterEditor == null) return;

            DrawLine(this.startPoint, this.endPoint);
        }

        /// <summary>
        /// 根据指定的首尾端点来绘制括弧。
        /// </summary>
        /// <param name="startPoint">首端点。</param>
        /// <param name="endPoint">尾端点。</param>
        private void DrawLine(Point startPoint, Point endPoint)
        {
            BracketOpenDirection direction;
            Point topLeft = new Point(Math.Min(startPoint.X, endPoint.X),
                Math.Min(startPoint.Y, endPoint.Y));
            Point bottomRight = new Point(Math.Max(startPoint.X, endPoint.X),
                Math.Max(startPoint.Y, endPoint.Y));
            Point topRight = new Point(bottomRight.X, topLeft.Y);
            Point bottomLeft = new Point(topLeft.X, bottomRight.Y);
            Point leftCenter = new Point(topLeft.X, topLeft.Y + (bottomRight.Y - topLeft.Y) / 2);
            Point rightCenter = new Point(bottomRight.X, leftCenter.Y);
            Point topCenter = new Point(topLeft.X + (bottomRight.X - topLeft.X) / 2, topLeft.Y);
            Point bottomCenter = new Point(topCenter.X, bottomRight.Y);
            Point center = new Point(topCenter.X, leftCenter.Y);

            if (Math.Abs(endPoint.Y - startPoint.Y) >= Math.Abs(endPoint.X - startPoint.X))
            {
                //左右开口
                if (endPoint.X >= startPoint.X)
                {
                    direction = BracketOpenDirection.Right;
                }
                else { direction = BracketOpenDirection.Left; }
            }
            else
            {
                //上下开口
                if (endPoint.Y >= startPoint.Y)
                {
                    direction = BracketOpenDirection.Down;
                }
                else { direction = BracketOpenDirection.Up; }

            }

            DrawLine(startPoint, endPoint, ref topLeft, ref bottomRight, ref topRight, ref bottomLeft,
                ref leftCenter, ref rightCenter, ref topCenter, ref bottomCenter, direction);

            RefreshTextPanelLocatin(startPoint, endPoint, ref topLeft, ref bottomRight, ref bottomLeft, direction);
        }

        /// <summary>
        /// 重定文本位置。
        /// </summary>
        /// <param name="topLeft">左上角位置。</param>
        /// <param name="bottomRight">右下角位置。</param>
        /// <param name="bottomLeft">左下角位置。</param>
        /// <param name="direction">方位。</param>
        private void LocateTextPanel(Point startPoint, Point endPoint, Point topLeft, Point bottomRight, Point bottomLeft, BracketOpenDirection direction)
        {
            Point textStart;

            switch (this.LineForm)
            {
                case BracketLineForms.HorizontalPointer:
                    {
                        if (startPoint.Y < endPoint.Y)
                        {
                            textStart = new Point(startPoint.X - this.mainBorder.ActualWidth / 2 - 2, startPoint.Y - this.mainBorder.ActualHeight);
                        }
                        else
                        {
                            textStart = new Point(startPoint.X - this.mainBorder.ActualWidth / 2 - 2, startPoint.Y);
                        }
                        break;
                    }
                case BracketLineForms.VerticalPointer:
                    {
                        if (startPoint.X < endPoint.X)
                        {
                            textStart = new Point(startPoint.X - this.mainBorder.ActualWidth, startPoint.Y - this.mainBorder.ActualHeight / 2 - 2);
                        }
                        else
                        {
                            textStart = new Point(startPoint.X, startPoint.Y - this.mainBorder.ActualHeight / 2 - 2);
                        }
                        break;
                    }
                case BracketLineForms.Bezier:
                    {
                        #region 贝塞尔曲线形态
                        switch (direction)
                        {
                            case BracketOpenDirection.Right:
                                {
                                    textStart = new Point(startPoint.X - this.mainBorder.ActualWidth, startPoint.Y - this.mainBorder.ActualHeight / 2);
                                    break;
                                }
                            case BracketOpenDirection.Left:
                                {
                                    textStart = new Point(startPoint.X + 2, startPoint.Y - this.mainBorder.ActualHeight / 2);
                                    break;
                                }
                            case BracketOpenDirection.Down:
                                {
                                    textStart = new Point(startPoint.X - this.mainBorder.ActualWidth / 2, startPoint.Y - this.mainBorder.ActualHeight);
                                    break;
                                }
                            default:
                                {
                                    textStart = new Point(startPoint.X - this.mainBorder.ActualWidth / 2, startPoint.Y);
                                    break;
                                }
                        }

                        break;
                        #endregion
                    }
                case BracketLineForms.Brace://与括弧形态相同
                default:
                    {
                        #region 括弧形态
                        if (isTextAtClose)
                        {
                            switch (direction)
                            {
                                case BracketOpenDirection.Right:
                                    {
                                        double offset = ((bottomLeft.Y - topLeft.Y) - this.mainBorder.ActualHeight) / 2;

                                        textStart = new Point(topLeft.X - this.mainBorder.ActualWidth - 6,
                                            topLeft.Y + offset - 2);
                                        break;
                                    }
                                case BracketOpenDirection.Left:
                                    {
                                        double offset = ((bottomLeft.Y - topLeft.Y) - this.mainBorder.ActualHeight) / 2;

                                        textStart = new Point(bottomRight.X + 6,
                                            topLeft.Y + offset - 2);
                                        break;
                                    }
                                case BracketOpenDirection.Down:
                                    {
                                        double offset = ((bottomRight.X - topLeft.X) - this.mainBorder.ActualWidth) / 2;

                                        textStart = new Point(topLeft.X + offset - 2, topLeft.Y - this.mainBorder.ActualHeight - 6);
                                        break;
                                    }
                                default:
                                    {
                                        double offset = ((bottomRight.X - topLeft.X) - this.mainBorder.ActualWidth) / 2;

                                        textStart = new Point(topLeft.X + offset - 2, bottomRight.Y + 6);
                                        break;
                                    }
                            }
                        }
                        else
                        {
                            switch (direction)
                            {
                                case BracketOpenDirection.Left:
                                    {
                                        double offset = ((bottomLeft.Y - topLeft.Y) - this.mainBorder.ActualHeight) / 2;

                                        textStart = new Point(topLeft.X - this.mainBorder.ActualWidth,
                                            topLeft.Y + offset);
                                        break;
                                    }
                                case BracketOpenDirection.Right:
                                    {
                                        double offset = ((bottomLeft.Y - topLeft.Y) - this.mainBorder.ActualHeight) / 2;

                                        textStart = new Point(bottomRight.X,
                                            topLeft.Y + offset);
                                        break;
                                    }
                                case BracketOpenDirection.Up:
                                    {
                                        double offset = ((bottomRight.X - topLeft.X) - this.mainBorder.ActualWidth) / 2;

                                        textStart = new Point(topLeft.X + offset, topLeft.Y - this.mainBorder.ActualHeight);
                                        break;
                                    }
                                default:
                                    {
                                        double offset = ((bottomRight.X - topLeft.X) - this.mainBorder.ActualWidth) / 2;

                                        textStart = new Point(topLeft.X + offset, bottomRight.Y);
                                        break;
                                    }
                            }
                        }
                        #endregion
                        break;
                    }
            }

            Canvas.SetLeft(this.mainBorder, textStart.X);
            Canvas.SetTop(this.mainBorder, textStart.Y);
        }
        
        /// <summary>
        /// 以basePoint为基础坐标，画出四象限。
        /// 取出pt在哪个象限中。
        /// </summary>
        /// <param name="pt"></param>
        /// <param name="basePoint"></param>
        /// <returns></returns>
        private int Getquadrant(Point pt, Point basePoint)
        {
            if (pt.X > basePoint.X)
            {
                if (pt.Y > basePoint.Y)
                {
                    return 4;
                }
                else
                {
                    return 1;
                }
            }
            else
            {
                if (pt.Y > basePoint.Y)
                {
                    return 3;
                }
                else
                {
                    return 2;
                }
            }
        }

        public override string GetRelativeOuterXml(Point baseCopyTopLeft)
        {
            if (this.xmlData == null) return string.Empty;

            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseCopyTopLeft.X,
                oldStartPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.StartPointTag, newStartPoint.ToString());

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseCopyTopLeft.X,
                oldEndPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.EndPointTag, newEndPoint.ToString());

            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append(this.xmlData.OuterXml);

            this.xmlData.SetAttribute(XmlTags.StartPointTag, oldStartPoint.ToString());
            this.xmlData.SetAttribute(XmlTags.EndPointTag, oldEndPoint.ToString());
            return sb.ToString();
        }
        
        /// <summary>
        /// 这个虚方法是用以查看本部件是否在选定框的内部。
        /// 线型部件，各有各的计算办法。
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public override bool IsInRect(Rect rect)
        {
            //return base.IsInRect(rect);//这个要屏蔽。
            bool isInRect = base.IsInRect(rect);
            if (isInRect)
            {
                return true;
            }
            else
            {
                //这个法子还不完善。线是否“穿过”矩形还得另想办法。
                return rect.Contains(startPoint) || rect.Contains(endPoint);
            }
        }
        
        public override void RefreshLineDash()
        {
            switch (lineDash)
            {
                case LineDashType.DashType.Dash:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.dashCollection; break;
                    }
                case LineDashType.DashType.DashDotDot:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.dashDotDotCollection; break;
                    }
                case LineDashType.DashType.Dot:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.dotCollection; break;
                    }
                case LineDashType.DashType.Solid:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.solidCollection; break;
                    }
                default:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.dashDotCollection; break;
                    }
            }
        }

        public override void RefreshWidgetLineWidth()
        {
            base.RefreshWidgetLineWidth();//RefreshLocation会调用。

            mainPath.StrokeThickness = widgetLineWidth;

            Point topLeft = new Point(Math.Min(startPoint.X, endPoint.X),
                 Math.Min(startPoint.Y, endPoint.Y));
            Point bottomRight = new Point(Math.Max(startPoint.X, endPoint.X),
                Math.Max(startPoint.Y, endPoint.Y));

            Point topRight = new Point(bottomRight.X, topLeft.Y);
            Point bottomLeft = new Point(topLeft.X, bottomRight.Y);
            Point leftCenter = new Point(topLeft.X, topLeft.Y + (bottomRight.Y - topLeft.Y) / 2);
            Point rightCenter = new Point(bottomRight.X, leftCenter.Y);
            Point topCenter = new Point(topLeft.X + (bottomRight.X - topLeft.X) / 2, topLeft.Y);
            Point bottomCenter = new Point(topCenter.X, bottomRight.Y);
            Point center = new Point(topCenter.X, leftCenter.Y);

            BracketOpenDirection direction = BracketDirection;

            DrawLine(this.startPoint, this.endPoint, ref topLeft, ref bottomRight, ref topRight, ref bottomLeft,
                ref leftCenter, ref rightCenter, ref topCenter, ref bottomCenter, direction);
        }

        public override void RefreshLocation()
        {
            base.RefreshLocation();

            DrawLine();

            RefreshArrows();
            RefreshWidgetLineWidth();//与线、箭头相关的代码。
        }

        private void DrawLine(Point startPoint, Point endPoint, ref Point topLeft,
            ref Point bottomRight, ref Point topRight, ref Point bottomLeft, ref Point leftCenter,
            ref Point rightCenter, ref Point topCenter, ref Point bottomCenter, BracketOpenDirection direction)
        {
            switch (this.LineForm)
            {
                case BracketLineForms.HorizontalPointer:
                    {
                        #region 横指向符
                        Point controlPoint = new Point(startPoint.X, endPoint.Y);

                        startArrowPathFigure.StartPoint = startPoint;
                        Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                            startPoint, controlPoint, widgetLineWidth * 2);
                        startArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                };
                        mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                        endArrowPathFigure.StartPoint = endPoint;
                        Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                            endPoint, controlPoint, widgetLineWidth * 2);
                        endArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                };

                        mainPolyBezierSegment.Points = new PointCollection()
                                {
                                    controlPoint,controlPoint,apEnd.ArrowRealTopPoint,
                                };
                        break;
                        #endregion
                    }
                case BracketLineForms.VerticalPointer:
                    {
                        #region 纵指向符
                        Point controlPoint = new Point(endPoint.X, startPoint.Y);

                        startArrowPathFigure.StartPoint = startPoint;
                        Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                            startPoint, controlPoint, widgetLineWidth * 2);
                        startArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                };
                        mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                        endArrowPathFigure.StartPoint = endPoint;
                        Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                            endPoint, controlPoint, widgetLineWidth * 2);
                        endArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                };

                        mainPolyBezierSegment.Points = new PointCollection()
                                {
                                    controlPoint,controlPoint,apEnd.ArrowRealTopPoint,
                                };
                        break;
                        #endregion
                    }
                case BracketLineForms.Square:
                    {
                        #region 方括弧形态
                        switch (direction)
                        {
                            case BracketOpenDirection.Right:
                                {
                                    startArrowPathFigure.StartPoint = topRight;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        topRight, topLeft, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = bottomRight;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        bottomRight, bottomLeft, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        topLeft,topLeft,leftCenter,bottomLeft,bottomLeft,apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                            case BracketOpenDirection.Left:
                                {
                                    startArrowPathFigure.StartPoint = topLeft;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        topLeft, topRight, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = bottomLeft;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        bottomLeft, bottomRight, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        topRight,topRight,rightCenter,bottomRight,bottomRight,apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                            case BracketOpenDirection.Up:
                                {
                                    startArrowPathFigure.StartPoint = topLeft;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        topLeft, bottomLeft, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = topRight;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        topRight, bottomRight, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        bottomLeft,bottomLeft,bottomCenter,bottomRight,bottomRight,apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                            case BracketOpenDirection.Down:
                                {
                                    startArrowPathFigure.StartPoint = bottomLeft;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        bottomLeft, topLeft, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = bottomRight;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        bottomRight, topRight, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        topLeft,topLeft,topCenter,topRight,topRight,apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                        }
                        break;
                        #endregion
                    }
                case BracketLineForms.Brace:
                    {
                        #region 小括弧形态
                        switch (direction)
                        {
                            case BracketOpenDirection.Right:
                                {
                                    startArrowPathFigure.StartPoint = topRight;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        topRight, topLeft, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = bottomRight;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        bottomRight, bottomLeft, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        topLeft,bottomLeft,apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                            case BracketOpenDirection.Left:
                                {
                                    startArrowPathFigure.StartPoint = topLeft;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        topLeft, topRight, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = bottomLeft;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        bottomLeft, bottomRight, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        topRight,bottomRight,apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                            case BracketOpenDirection.Up:
                                {
                                    startArrowPathFigure.StartPoint = topLeft;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        topLeft, bottomLeft, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = topRight;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        topRight, bottomRight, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        bottomLeft,bottomRight,apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                            case BracketOpenDirection.Down:
                                {
                                    startArrowPathFigure.StartPoint = bottomLeft;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        bottomLeft, topLeft, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = bottomRight;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        bottomRight, topRight, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        topLeft,topRight,apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                        }
                        break;
                        #endregion
                    }
                case BracketLineForms.Bezier:
                    {
                        #region 贝塞尔曲线形态（半个花括弧）
                        switch (direction)
                        {
                            case BracketOpenDirection.Left:
                            case BracketOpenDirection.Right:
                                {
                                    startArrowPathFigure.StartPoint = startPoint;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        startPoint, new Point(endPoint.X, startPoint.Y), widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };

                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = endPoint;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                       endPoint, new Point(startPoint.X, endPoint.Y), widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        new Point(endPoint.X,startPoint.Y),
                                        new Point(startPoint.X,endPoint.Y),
                                        apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                            case BracketOpenDirection.Up:
                            case BracketOpenDirection.Down:
                                {
                                    startArrowPathFigure.StartPoint = startPoint;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        startPoint, new Point(startPoint.X, endPoint.Y), widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                    };

                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = endPoint;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        endPoint, new Point(endPoint.X, startPoint.Y), widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                    {
                                        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                    };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                    {
                                        new Point(startPoint.X,endPoint.Y),
                                        new Point(endPoint.X,startPoint.Y),
                                        apEnd.ArrowRealTopPoint,
                                    };
                                    break;
                                }
                        }
                        break;
                        #endregion
                    }
                default:
                    {
                        #region 花括弧形态
                        switch (direction)
                        {
                            case BracketOpenDirection.Right:
                                {
                                    startArrowPathFigure.StartPoint = topRight;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        topRight, topLeft, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = bottomRight;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        bottomRight, bottomLeft, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                {
                                   topLeft,rightCenter,leftCenter,rightCenter,bottomLeft,apEnd.ArrowRealTopPoint,
                                };
                                    break;
                                }
                            case BracketOpenDirection.Left:
                                {
                                    startArrowPathFigure.StartPoint = topLeft;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        topLeft, topRight, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = bottomLeft;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        bottomLeft, bottomRight, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                {
                                    topRight,leftCenter,rightCenter,leftCenter,bottomRight,apEnd.ArrowRealTopPoint,
                                };
                                    break;
                                }
                            case BracketOpenDirection.Up:
                                {
                                    startArrowPathFigure.StartPoint = topLeft;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        topLeft, bottomLeft, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = topRight;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        topRight, bottomRight, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                {
                                    bottomLeft,topCenter,bottomCenter,topCenter,bottomRight,apEnd.ArrowRealTopPoint,
                                };
                                    break;
                                }
                            case BracketOpenDirection.Down:
                                {
                                    startArrowPathFigure.StartPoint = bottomLeft;
                                    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                                        bottomLeft, topLeft, widgetLineWidth * 2);
                                    startArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                                };
                                    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

                                    endArrowPathFigure.StartPoint = bottomRight;
                                    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                                        bottomRight, topRight, widgetLineWidth * 2);
                                    endArrowPolyLineSegment.Points = new PointCollection()
                                {
                                    apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                                };

                                    mainPolyBezierSegment.Points = new PointCollection()
                                {
                                    topLeft,bottomCenter,topCenter,bottomCenter,topRight,apEnd.ArrowRealTopPoint,
                                };
                                    break;
                                }
                        }
                        break;
                        #endregion
                    }
            }
        }

        public override void RefreshPointWhenGroupIn(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseTopLeft.X,
                oldStartPoint.Y - baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseTopLeft.X,
                oldEndPoint.Y - baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public override void RefreshPointWhenGroupOut(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X + baseTopLeft.X,
                oldStartPoint.Y + baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X + baseTopLeft.X,
                oldEndPoint.Y + baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public override void RefreshWidgetLineColor()
        {
            startArrowPath.Stroke = endArrowPath.Stroke =
                startArrowPath.Fill = endArrowPath.Fill =
                    mainPath.Stroke = this.WidgetLineColor;
        }

        public override void RefreshIsShadowVisible()
        {
            base.RefreshIsShadowVisible();

            if (isShadowVisible)
            {
                this.mainPath.Effect = Widget.ShadowEffect;
            }
            else
            {
                this.mainPath.Effect = null;
            }
        }

        public override void RefreshTextPanelLocatin()
        {
            Point topLeft = new Point(Math.Min(startPoint.X, endPoint.X),
                Math.Min(startPoint.Y, endPoint.Y));
            Point bottomRight = new Point(Math.Max(startPoint.X, endPoint.X),
                Math.Max(startPoint.Y, endPoint.Y));

            Point topRight = new Point(bottomRight.X, topLeft.Y);
            Point bottomLeft = new Point(topLeft.X, bottomRight.Y);
            Point leftCenter = new Point(topLeft.X, topLeft.Y + (bottomRight.Y - topLeft.Y) / 2);
            Point rightCenter = new Point(bottomRight.X, leftCenter.Y);
            Point topCenter = new Point(topLeft.X + (bottomRight.X - topLeft.X) / 2, topLeft.Y);
            Point bottomCenter = new Point(topCenter.X, bottomRight.Y);
            Point center = new Point(topCenter.X, leftCenter.Y);

            BracketOpenDirection direction = BracketDirection;

            RefreshTextPanelLocatin(this.startPoint, this.endPoint, ref topLeft, ref bottomRight, ref bottomLeft, direction);
        }

        private void RefreshTextPanelLocatin(Point startPoint, Point endPoint,
            ref Point topLeft, ref Point bottomRight, ref Point bottomLeft, BracketOpenDirection direction)
        {
            LocateTextPanel(startPoint, endPoint, topLeft, bottomRight, bottomLeft, direction);
        }

        /// <summary>
        /// 刷新文本区旋转角度。
        /// </summary>
        public void RefreshTextRotateAngle()
        {
            if (this.mainBorder.RenderTransformOrigin != DefaultRenderCenter)
            {
                this.mainBorder.RenderTransformOrigin = DefaultRenderCenter;
            }

            if (this.textRotateAngle == 0)
            {
                this.mainBorder.RenderTransform = DefaultRotateTransform;
            }
            else
            {
                this.mainBorder.RenderTransform = new RotateTransform(textRotateAngle);
            }
        }

        #endregion


        #region 其它=========================================================================================================

        public enum BracketOpenDirection { Up, Down, Left, Right }

        //private enum ControlDraggingType { Start, End, None, CenterCP }
        //2012年5月30日已移植并合并至Enums.LineCtrlDraggingType文件中。

        private static DoubleCollection dashArray;

        #endregion

    }
}
